<template>
  <div :class="{
          'my-sparkle': (anmSparkle.active && currentSwitch),
          'my-scale': (anmScale.active && currentSwitch),
          'my-visible' : (anmVisible.active && currentSwitch)
        }"
       @click="onClick"
       @dblclick="onDoubleClick"
  >
    <canvas
      ref="myCanvasRef"
      class="my-canvas-container"
      :width="detail.position.w"
      :height="detail.position.h"
      
    >
      Your browser does not support the HTML5 canvas tag.
    </canvas>
  </div>
</template>

<script lang="ts">
import { defineComponent, nextTick, onMounted, PropType, ref, toRefs, watch } from 'vue';
import { CGraphEntity, CVariableDataItem } from 'stores/editorModels';
import { CTuplePropertyItem, TupleType } from './basicViewModel'
import { useMessageNotify } from 'src/hook/common/useMessageNotify';
import { useCanvasDraw } from 'components/views/basic/useCanvasDraw';
import { cataItem } from 'src/hook/common/useCatalogType';
import { useMotion } from 'src/hook/editor/useMotion';
import { useEvent } from 'src/hook/editor/useEvent';
import { EnumEventType } from 'src/util/SelectBoxOption';


export default defineComponent({
  name: 'ViewBasicTuple',
  props: {
    detail: {        //组件属性
      type: Object as PropType<CGraphEntity>,
      required: true
    },
    dynamicData: {   //动态数据库
      type: Array as PropType<CVariableDataItem[]>,
      default: () => {
        return [] as CVariableDataItem[]
      }
    },
    currentSwitch: {   //动效和事件开关
      type: Boolean,
      default: () => {
        return false;
      }
    },
    motionTypeArr: {   //动效类型
      type: Array as PropType<cataItem[]>,
      default: () => {
        return [] as cataItem[]
      }
    },
    operatorTypeArr: {  //操作符类型
      type: Array as PropType<cataItem[]>,
      default: () => {
        return [] as cataItem[]
      }
    },
    eventTypeArr: {    //事件类型
      type: Array as PropType<cataItem[]>,
      default: () => {
        return [] as cataItem[]
      }
    },
    operationTypeArr: {   //操作行为类型
      type: Array as PropType<cataItem[]>,
      default: () => {
        return [] as cataItem[]
      }
    }
  },
  emits: ['update-event'],

  setup (props, context) {
    //数据解构TupleType
    const {
      detail,
      dynamicData,
      currentSwitch,
      motionTypeArr,
      operatorTypeArr,
      eventTypeArr,
      operationTypeArr
    } = toRefs(props);

    //*********************************************************************************************
    //      动效
    //*********************************************************************************************
    const {
      anmVisible,
      anmScale,
      anmSparkle,
      readVariableTbl,
      configMotion,
      processMotion
    } = useMotion();

    //*********************************************************************************************
    //      事件
    //*********************************************************************************************
    const {
      myEventList,
      readEventVariableTbl,
      configEvent
    } = useEvent();

    let myCanvasRef = ref<HTMLCanvasElement | null>(null);
    let ctx = ref<CanvasRenderingContext2D | null>(null);
    let param = ref<CTuplePropertyItem>({
      title: 'hello',
      fontSize: 14,

      cr: 0,

      internR: 10,
      externR: 20,

      sides: 6,
      radius: 20,
      
      imgURL: '',
      marginX: 0,
      marginY: 0,

      borderColor: 'black',
      borderWidth: 1,
      fillColor: 'transparent',
      fontColor: '#000000',
      gradientColor: 'linear-gradient(0deg, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 1) 100%)'
    });
    let myTimer = ref();  //解决单双击问题

    //画图
    const {
      drawText,
      drawTextBorder,
      drawLine,
      drawDashedLine,
      drawLineArrow,
      drawRoundRect,
      drawTriangle,
      drawCircle,
      drawDoubleCircle,
      drawEllipse,
      drawEqualSidesPolygon,
      drawImage,
      clearRect
    } = useCanvasDraw();

    //定义画布
    const draw = (ca: CanvasRenderingContext2D, mType: string, graph: CGraphEntity,  brush: CTuplePropertyItem) => {
      let num1 = 0, num2 = 0;
      let w = 0, h = 0;
      //清除画布
      clearRect(ca, { x: 0, y: 0 }, graph.position.w, graph.position.h, 'white');

      //目的让父组件显示全
      w = graph.position.w - 4;
      h = graph.position.h - 4;
      switch (mType) {
        case TupleType.TEXT_TYPE:  
          num1 = (brush.fontSize === undefined) ? 14 : brush.fontSize;
          drawText(ca, { x: 1, y: 1 + h / 2 }, String(brush.title), num1, brush.borderColor);
          break;
        case TupleType.TEXT_BORDER_TYPE:  
          num1 = (brush.fontSize === undefined) ? 14 : brush.fontSize;
          drawTextBorder(ca, {x: 1, y: 1 + h / 2}, String(brush.title), num1, String(brush.fontColor), 
          brush.borderColor, Number(brush.marginY), Number(brush.marginX), brush.fillColor)
          break;
        case TupleType.LINE_TYPE:
          drawLine(ca, { x: 1, y: 1 + h / 2 },
            { x: w, y: h / 2 }, brush.borderWidth, brush.borderColor);
          break;
        case TupleType.DASHED_LINE_TYPE:
          drawDashedLine(ca, {x: 1, y: 1 + h / 2}, { x: w, y: h / 2 }, brush.borderWidth, brush.borderColor, graph.position.w);
          break;
        case TupleType.LINE_ARROW_TYPE:
          drawLineArrow(ca, { x: 1, y: 1 + h / 2 },
            { x: w, y: h / 2 }, brush.borderWidth, brush.borderColor);
          break;
        case TupleType.RECT_TYPE:
          num1 = (brush.cr === undefined) ? 0 : brush.cr;
          drawRoundRect(ca, { x: 1, y: 1 }, w, h,
            num1, num1, brush.borderWidth, brush.borderColor, brush.fillColor);
          break;
        case TupleType.TRIANGLE_TYPE:
          drawTriangle(ca, { x: 1 + w / 2, y: 1 + h / 2 }, w, h,
            brush.borderWidth, brush.borderColor, brush.fillColor);
          break;
        case TupleType.CIRCLE_TYPE:
          num1 = (w <= h) ? w : h;
          drawCircle(ca, { x: 1 + w / 2, y: 1 + h / 2 },
            num1 / 2, brush.borderWidth, brush.borderColor, brush.fillColor);
          break;
        case TupleType.DOUBLE_CIRCLE_TYPE:
          num1 = (brush.internR === undefined) ? 10 : brush.internR;
          num2 = (brush.externR === undefined) ? 20 : brush.externR;
          drawDoubleCircle(ca, { x: 1 + w / 2, y: 1 + h / 2 }, num1, num2,
            brush.borderWidth, brush.borderColor, brush.fillColor);
          break;
        case TupleType.ELLIPSE_TYPE:
          drawEllipse(ca, { x: 1 + w / 2, y: 1 + h / 2 }, w / 2, h / 2,
            brush.borderWidth, brush.borderColor, brush.fillColor);
          break;
        case TupleType.EQUAL_POLYGON_TYPE:
          num1 = (brush.sides === undefined) ? 3 : brush.sides;
          num2 = (brush.radius === undefined) ? 3 : brush.radius;
          drawEqualSidesPolygon(ca, { x: 1 + w / 2, y: 1 + h / 2 }, num1, num2,
            brush.borderWidth, brush.borderColor, brush.fillColor);
          break;
        case TupleType.IMAGE_TYPE:
          drawImage(ca, { x: 1, y: 1 }, '', w, h);
          break;
        default: break;
      }
    };

    //配置属性
    const configProperty = () => {
      if ((detail.value) && (detail.value?.propsItem) &&
        (detail.value?.propsItem.length > 0)) {
        let i = 0;
        let num1, num2, num3;

        switch (detail.value.comValue) {
          case TupleType.TEXT_TYPE:
            //颜色，线粗，填充颜色,文字，字号
            param.value.borderColor = detail.value.propsItem[i++].value;
            num1 = parseInt(detail.value.propsItem[i++].value);
            param.value.fillColor = detail.value.propsItem[i++].value;
            param.value.title = detail.value.propsItem[i++].value;
            num2 = parseInt(detail.value.propsItem[i++].value);
            if (!isNaN(num1) && !isNaN(num2)) {
              param.value.borderWidth = num1;
              param.value.fontSize = num2;
            } else {
              showMessage('drawText属性值不是数字！');
            }
            break;
          case TupleType.TEXT_BORDER_TYPE:
            param.value.title = detail.value.propsItem[i++].value;
            param.value.borderColor = detail.value.propsItem[i++].value;
            param.value.fontColor = detail.value.propsItem[i++].value;
            param.value.borderWidth = parseInt(detail.value.propsItem[i++].value);
            param.value.fontSize = parseInt(detail.value.propsItem[i++].value);
            param.value.marginY = parseInt(detail.value.propsItem[i++].value);
            param.value.marginX = parseInt(detail.value.propsItem[i++].value);
            param.value.fillColor = detail.value.propsItem[i++].value;
            break;
          case TupleType.LINE_TYPE:
            //颜色，线粗，填充颜色
            param.value.borderColor = detail.value.propsItem[i++].value;
            num1 = parseInt(detail.value.propsItem[i++].value);
            param.value.fillColor = detail.value.propsItem[i++].value;

            if (!isNaN(num1)) {
              param.value.borderWidth = num1;
            } else {
              showMessage('drawLine属性值不是数字！');
            }
            break;
          case TupleType.DASHED_LINE_TYPE:
            param.value.borderColor = detail.value.propsItem[i++].value;
            param.value.borderWidth = parseInt(detail.value.propsItem[i++].value)
            
            break;
          case TupleType.LINE_ARROW_TYPE:
            //颜色，线粗，填充颜色
            param.value.borderColor = detail.value.propsItem[i++].value;
            num1 = parseInt(detail.value.propsItem[i++].value);
            param.value.fillColor = detail.value.propsItem[i++].value;

            if (!isNaN(num1)) {
              param.value.borderWidth = num1;
            } else {
              showMessage('drawLine属性值不是数字！');
            }
            break;
          case TupleType.RECT_TYPE:
            //颜色，线粗，填充颜色,圆角
            param.value.borderColor = detail.value.propsItem[i++].value;
            num1 = parseInt(detail.value.propsItem[i++].value);
            param.value.fillColor = detail.value.propsItem[i++].value;
            num2 = parseInt(detail.value.propsItem[i++].value);
            param.value.gradientColor = detail.value.propsItem[i++].value;

            if (!isNaN(num1) && !isNaN(num2)) {
              param.value.borderWidth = num1;
              param.value.cr = num2;
            } else {
              showMessage('drawRect属性值不是数字！');
            }
            break;
          case TupleType.TRIANGLE_TYPE:
            //颜色，线粗，填充颜色
            param.value.borderColor = detail.value.propsItem[i++].value;
            num1 = parseInt(detail.value.propsItem[i++].value);
            param.value.fillColor = detail.value.propsItem[i++].value;

            if (!isNaN(num1)) {
              param.value.borderWidth = num1;
            } else {
              showMessage('drawTriangle属性值不是数字！');
            }
            break;
          case TupleType.CIRCLE_TYPE:
            //颜色，线粗，填充颜色
            param.value.borderColor = detail.value.propsItem[i++].value;
            num1 = parseInt(detail.value.propsItem[i++].value);
            param.value.fillColor = detail.value.propsItem[i++].value;

            if (!isNaN(num1)) {
              param.value.borderWidth = num1;
            } else {
              showMessage('drawCircle属性值不是数字！');
            }
            break;
          case TupleType.DOUBLE_CIRCLE_TYPE:
            //颜色，线粗，填充颜色，内圆半径，外圆半径
            param.value.borderColor = detail.value.propsItem[i++].value;
            num1 = parseInt(detail.value.propsItem[i++].value);
            param.value.fillColor = detail.value.propsItem[i++].value;
            num2 = parseInt(detail.value.propsItem[i++].value);
            num3 = parseInt(detail.value.propsItem[i++].value);
            if (!isNaN(num1) && !isNaN(num2) && !isNaN(num3)) {
              param.value.borderWidth = num1;
              param.value.internR = num2;
              param.value.externR = num3;
            } else {
              showMessage('drawDoubleCircle属性值不是数字！');
            }
            break;
          case TupleType.ELLIPSE_TYPE:
            //颜色，线粗，填充颜色
            param.value.borderColor = detail.value.propsItem[i++].value;
            num1 = parseInt(detail.value.propsItem[i++].value);
            param.value.fillColor = detail.value.propsItem[i++].value;

            if (!isNaN(num1)) {
              param.value.borderWidth = num1;
            } else {
              showMessage('drawEllipse属性值不是数字！');
            }
            break;
          case TupleType.EQUAL_POLYGON_TYPE:
            //颜色，线粗，填充颜色,边数，外切圆半径
            param.value.borderColor = detail.value.propsItem[i++].value;
            num1 = parseInt(detail.value.propsItem[i++].value);
            param.value.fillColor = detail.value.propsItem[i++].value;
            num2 = parseInt(detail.value.propsItem[i++].value);
            num3 = parseInt(detail.value.propsItem[i++].value);
            if (!isNaN(num1) && !isNaN(num2) && !isNaN(num3)) {
              param.value.borderWidth = num1;
              param.value.sides = num2;
              param.value.radius = num3;
            } else {
              showMessage('drawEqualPolygon属性值不是数字！');
            }
            break;
          case TupleType.IMAGE_TYPE:
            //颜色，线粗，填充颜色,url,
            param.value.borderColor = detail.value.propsItem[i++].value;
            num1 = parseInt(detail.value.propsItem[i++].value);
            param.value.fillColor = detail.value.propsItem[i++].value;
            param.value.imgURL = detail.value.propsItem[i++].value;
            if (!isNaN(num1)) {
              param.value.borderWidth = num1;
            } else {
              showMessage('drawImage属性值不是数字！');
            }
            break;
          default:
            break;
        }
      }
    }

    //错误通知
    const {
      showMessage
    } = useMessageNotify();

    //单击事件
    const onClick = () => {
      //决定是否响应单击事件
      if (!currentSwitch.value) {
        return;
      }

      //删除定时器
      if (myTimer.value) {
        clearTimeout(myTimer.value)
      }

      //定时响应
      myTimer.value = setTimeout(() => {
        //操作
        myEventList.value.forEach((item) => {
          if (item.eventType === EnumEventType.EVT_CLICKED) {
            context.emit('update-event', {
              operationType: item.operationType,
              url: item.url,
              msg: item.msg
            });
          }
        });
      }, 200);
    }

    //双击事件
    const onDoubleClick = () => {
      //决定是否响应单击事件
      if (!currentSwitch.value) {
        return;
      }

      //删除定时器
      if (myTimer.value) {
        clearTimeout(myTimer.value)
      }

      //操作
      myEventList.value.forEach((item) => {
        if (item.eventType === EnumEventType.EVT_DOUBLE_CLICKED) {
          context.emit('update-event', {
            operationType: item.operationType,
            url: item.url,
            msg: item.msg
          });
        }
      });
    }

    //初始化
    const init = () => {
      //配置属性
      configProperty();
    };

    // 监视数据变化,detail每个属性变化都能监听到
    watch(() => detail, () => {
      //发生变化时更新数据
      configProperty();

      //配置动效
      configMotion(detail.value.motionItem, motionTypeArr.value, operatorTypeArr.value);

      //配置事件
      configEvent(detail.value.eventItem, eventTypeArr.value, operationTypeArr.value, operatorTypeArr.value);

      //延时绘图,必须用延时
      nextTick(() => {
        if (ctx.value) {
          draw(ctx.value, detail.value.comValue, detail.value, param.value);
        }
      });
    }, { deep: true });

    //监视数据变化
    watch(() => dynamicData, () => {
      //可见
      let vData = readVariableTbl(dynamicData.value, anmVisible.value.variableId);
      if (vData) {
        processMotion(anmVisible.value.motionType, vData);
      }

      //缩放
      vData = readVariableTbl(dynamicData.value, anmScale.value.variableId);
      if (vData) {
        processMotion(anmScale.value.motionType, vData);
      }

      //闪烁
      vData = readVariableTbl(dynamicData.value, anmSparkle.value.variableId);
      if (vData) {
        processMotion(anmSparkle.value.motionType, vData);
      }

      //事件,传递给父节点
      myEventList.value.forEach((item) => {
        if ((item.eventType === EnumEventType.EVT_VAR_CHANGED) && (item.variation)) {
          vData = readEventVariableTbl(dynamicData.value, item.variation.variableId);
          if (vData) {
            context.emit('update-event', {
              operationType: item.operationType,
              url: item.url,
              msg: item.msg
            });
          }
        }
      });
    }, { deep: true });

    // 挂载组件
    onMounted(() => {
      //初始化
      init();

      //延时画图
      nextTick(() => {
        //创建画布
        if (myCanvasRef.value) {
          ctx.value = myCanvasRef.value.getContext('2d');
          if (ctx.value) {
            draw(ctx.value, detail.value.comValue, detail.value, param.value);
          }
        }
      });
    });

    return {
      detail,
      currentSwitch,
      myCanvasRef,
      anmVisible,
      anmScale,
      anmSparkle,
      onClick,
      onDoubleClick
    };
  }
});
</script>

<style lang="scss" scoped>
.my-canvas-container {
  padding: 0;
  margin: 0;
}
</style>
